package core

import (
	"io"
	"openzbox.com/driver/conn/serial"
	"openzbox.com/log"
)

/*
type RS232Port struct {
	Name    string `json:"name"`
	Type    string `json:"type"`
	Dev     string `json:"dev"`
	R120    bool   `json:"r120,omitempty"`
	Baud    int    `json:"baud"`
	Booton  bool   `json:"booton"`
	Ioctrl  string `json:"ioctrl,omitempty"`
	com     io.ReadWriteCloser
	DataBit uint
	StopBit uint
	Options serial.OpenOptions
}*/

type RS232Port struct {
	Name string `json:"name"`
	Type string `json:"type"`
	//R120   bool               `json:"r120,omitempty"`
	Booton bool          `json:"booton"`
	Ioctrl string        `json:"ioctrl,omitempty"`
	Opts   serial.Config `json:"opts"`

	com io.ReadWriteCloser `json:"-"`
	ch  chan bool
}

func (port *RS232Port) GetName() string {
	return port.Name
}
func (port *RS232Port) GetType() string {
	return port.Type
}
func (port *RS232Port) GetOpts() serial.Config {
	return port.Opts
}

func New232Port(name string, dtype string, opts serial.Config) (*RS232Port, error) {
	var s = &RS232Port{Name: name, Type: dtype, Opts: opts, ch: make(chan bool)}
	/*s.cmds = make(map[string](string))
	s.pwc = pca9554.NewPCA9554()
	s.pwc.SetAllOutput()*/
	return s, nil
}

/*打开串口*/
func (port *RS232Port) Open(callback Callback) error {
	//fmt.Println("IsClosed ", IsClosed(port.ch))
	fs, err := serial.Open(&port.Opts)
	if err != nil {
		//log.Fatalf("serial.Open: %v", err)
		return err
	}
	port.com = fs
	port.ch = make(chan bool)
	//fmt.Println("IsClosed ", IsClosed(port.ch))
	return nil
}

/*按参数打开串口*/
/*
func (port *RS232Port) OpenWithOpts(callback Uartallback, args ...interface{}) error {
	options := serial.Config{
		Address:  port.Opts.Address,
		BaudRate: (args[0]).(int),
		DataBits: (args[1]).(int),
		Parity:   (args[2]).(string),
		StopBits: (args[3]).(int),
	}*/
func (port *RS232Port) OpenWithOpts(callback Callback, args ...interface{}) error {
	options := args[0].(serial.Config)
	// Open the port.
	fs, err := serial.Open(&options)
	if err != nil {
		//log.Fatalf("serial.Open: %v", err)
		return err
	}
	port.com = fs
	port.ch = make(chan bool)
	//defer port.Close()

	go func(err error) {
		//dataline := make([]byte, 0)
		var dataline []byte
		for {
			select {
			case <-port.ch:
				log.Infof("close port %s.", port.Name)
				return
			default:
				buf := make([]byte, 1)
				rx, rerr := fs.Read(buf)
				if rerr != nil {
					if rerr != io.EOF {
						log.Errorf("Error reading from serial port: ", rerr)
						err = rerr // errors.New("")
						return
					}
				} else {
					buf = buf[:rx]
					//devid = string(bytes.Trim(buf, "\x00"))
					dataline = append(dataline, buf...)
					//if strings.HasSuffix(string(dataline), "\n") {
					//if rx > 0 && buf[0] == 0x0a {
					//lg函数本身已有换行，因此清除掉返回数据中的回车换行符
					//log.Infof(string(dataline))
					//清空数组以重新接受rs485数据
					callback(port.Name, dataline)
					dataline = []byte{}
					//break
					//}
					//callback(port.Name, buf)
				}
			}
		}
	}(err) /**/
	return err
}

func (port *RS232Port) SetOpts(c serial.Config) {
	port.Opts = c
}

func (port *RS232Port) SendString(data string) error {
	_, err := port.com.Write([]byte(data))
	return err
}

func (port *RS232Port) SendBytes(data []byte) error {
	_, err := port.com.Write(data)
	return err
}

/*关闭串口*/
func (port *RS232Port) Close() error {
	//fmt.Printf("port.com %v %v", port, port.com)
	close(port.ch)
	return port.com.Close()
}

/*
func IsClosed(ch <-chan bool) bool {
	select {
	case <-ch:
		return true
	default:
	}
	return false
}
*/

func (port *RS232Port) IsClosed() bool {
	select {
	case <-port.ch:
		return true
	default:
	}
	return false
}
